<template>
  <ZForm
    :fields="loginFields"
    :initial-values="loginFormData"
    :schema="loginSchema"
    @submit="onSubmit"
  >
    <template #password="{ field, handleChange }">
      <label class="label flex justify-between" for="password">
        <span>密码</span>
        <a
          class="mx-2 text-primary hover:text-secondary cursor-pointer"
          @click="resetPasswordShow = true"
        >
          忘记密码？
        </a>
      </label>
      <ZModal v-model="resetPasswordShow">
        <h3>重置登录密码</h3>
        <p>请输入您的邮箱地址，我们将向您发送重置密码的邮件。</p>
        <ZForm
          :fields="resetPasswordFields"
          :schema="resetPasswordSchema"
          :initial-values="resetPasswordFormData"
          @submit="onResetPasswordSubmit"
        >
          <div class="flex gap-1 justify-end">
            <ZButton
              class="mt-2"
              color="secondary"
              icon-class="icon-[mdi--restart] size-6"
              type="reset"
            >
              重置
            </ZButton>
            <ZButton
              class="mt-2"
              color="primary"
              icon-class="icon-[mdi--content-save] size-6"
              type="submit"
              :loading="isResetting"
            >
              重置登录密码
            </ZButton>
          </div>
        </ZForm>
      </ZModal>
      <input
        class="input input-bordered w-full"
        type="password"
        id="password"
        placeholder="请输入您的密码"
        :value="field.value"
        @input="handleChange"
      />
    </template>
    <template #token="{ handleChange }">
      <cap-widget
        id="cap"
        class="w-full"
        data-cap-api-endpoint="/api/cap/"
        @solve="($event: any) => handleChange($event.detail.token)"
        data-cap-i18n-verifying-label="验证中..."
        data-cap-i18n-initial-state="我是人类"
        data-cap-i18n-solved-label="我是人类"
        data-cap-i18n-error-label="错误"
        style="--cap-widget-width: calc(100% - 2rem)"
      ></cap-widget>
    </template>

    <ZButton
      class="mt-2"
      icon-class="icon-[mdi--login] size-6"
      color="primary"
      type="submit"
      :loading="isLoading"
    >
      登 录
    </ZButton>

    <div class="flex justify-center items-center p-4">
      <span>还没有账户?</span>
      <a
        class="mx-2 text-primary hover:text-secondary cursor-pointer"
        @click="emit('change')"
      >
        注册
      </a>
    </div>
  </ZForm>
</template>
<script setup lang="ts">
import "@cap.js/widget";

import { ref } from "vue";
import { useMutation } from "@pinia/colada";

import { z } from "zod";
import { ZForm, type FormFields } from "@/components/form";
import ZButton from "@/components/ui/ZButton.vue";
import ZModal from "@/components/ui/ZModal.vue";

import type { SubmissionContext } from "vee-validate";
import { useUserStore } from "@/stores/user";
import { useRouter } from "vue-router";
import { login, resetPassword } from "@/apis/user";

// 表单数据验证模式
const loginSchema = z.object({
  email: z
    .string({ message: "邮箱不能为空" })
    .email({ message: "请输入正确的邮箱" }),
  password: z
    .string({ message: "密码不能为空" })
    .min(6, { message: "密码长度不能少于6位" })
    .max(20, { message: "密码长度不能超过20位" }),
  token: z.string().min(1, { message: "请完成人机验证" }),
});

// 表单字段
const loginFields: FormFields = [
  {
    name: "email",
    label: "邮箱",
    type: "email",
    inputAttributes: {
      placeholder: "请输入您的邮箱地址",
    },
  },
  {
    name: "password",
  },
  {
    name: "token",
    label: "人机验证",
  },
];

const loginFormData = {
  email: "",
  password: "",
  token: "",
};

const { isLoading, mutateAsync } = useMutation({
  mutation: login,
});
const userStore = useUserStore();
const router = useRouter();

async function onSubmit(
  values: z.infer<typeof loginSchema>,
  { resetForm, setErrors }: SubmissionContext
) {
  // 发送登录请求
  const data = await mutateAsync(values);
  // 判断登录是否成功
  if (data.success) {
    // 保存用户状态
    userStore.login(data.object, data.token);
    // 重置表单
    resetForm();
    // 跳转首页
    router.push({ name: "home" });
  } else {
    // 设置错误信息
    if (data.errors) setErrors(data.errors);
  }
}

const emit = defineEmits<{
  (e: "change"): void;
}>();

// reset form
const resetPasswordShow = ref(false);
const resetPasswordSchema = z.object({
  email: z.string().email({ message: "请输入正确的邮箱" }),
});
const resetPasswordFields: FormFields = [
  {
    name: "email",
    label: "邮箱",
    type: "email",
  },
];
const resetPasswordFormData = {
  email: "",
};
const { isLoading: isResetting, mutateAsync: resetPasswordPost } = useMutation({
  mutation: resetPassword,
});
async function onResetPasswordSubmit(
  { email }: z.infer<typeof resetPasswordSchema>,
  { resetForm, setErrors }: SubmissionContext
) {
  const data = await resetPasswordPost(email);
  if (data?.success) {
    // 重置表单
    resetForm();
    // 关闭弹窗
    resetPasswordShow.value = false;
  } else {
    // 设置错误信息
    if (data?.errors) setErrors(data.errors);
  }
}
</script>
<style>
:root {
  --cap-background: var(--color-base-100);
  --cap-border-color: var(--color-base-300);
  --cap-border-radius: var(--radius-field);
}
</style>
